{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A single neuron\n",
    "\n",
    "This demo shows you how to construct and manipulate\n",
    "a single leaky integrate-and-fire (LIF) neuron.\n",
    "The LIF neuron is a simple, standard neuron model,\n",
    "and here it resides inside a neural 'population,'\n",
    "even though there is only one neuron."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "import nengo\n",
    "from nengo.utils.matplotlib import rasterplot"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Create the Neuron"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from nengo.dists import Uniform\n",
    "\n",
    "model = nengo.Network(label='A Single Neuron')\n",
    "with model:\n",
    "    neuron = nengo.Ensemble(\n",
    "        1,\n",
    "        dimensions=1,  # Represent a scalar\n",
    "        # Set intercept to 0.5\n",
    "        intercepts=Uniform(-.5, -.5),\n",
    "        # Set the maximum firing rate of the neuron to 100hz\n",
    "        max_rates=Uniform(100, 100),\n",
    "        # Set the neuron's firing rate to increase for positive input\n",
    "        encoders=[[1]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Provide Input to the Model\n",
    "\n",
    "Create an input node generating a cosine wave."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with model:\n",
    "    cos = nengo.Node(lambda t: np.cos(8 * t))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3: Connect the Network Elements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with model:\n",
    "    # Connect the input signal to the neuron\n",
    "    nengo.Connection(cos, neuron)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4: Add Probes\n",
    "\n",
    "Anything that is probed will collect the data it produces over time,\n",
    "allowing us to analyze and visualize it later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with model:\n",
    "    # The original input\n",
    "    cos_probe = nengo.Probe(cos)\n",
    "    # The raw spikes from the neuron\n",
    "    spikes = nengo.Probe(neuron.neurons)\n",
    "    # Subthreshold soma voltage of the neuron\n",
    "    voltage = nengo.Probe(neuron.neurons, 'voltage')\n",
    "    # Spikes filtered by a 10ms post-synaptic filter\n",
    "    filtered = nengo.Probe(neuron, synapse=0.01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 5: Run the Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with nengo.Simulator(model) as sim:  # Create the simulator\n",
    "    sim.run(1)  # Run it for 1 second"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 6: Plot the Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the decoded output of the ensemble\n",
    "plt.figure()\n",
    "plt.plot(sim.trange(), sim.data[filtered])\n",
    "plt.plot(sim.trange(), sim.data[cos_probe])\n",
    "plt.xlim(0, 1)\n",
    "\n",
    "# Plot the spiking output of the ensemble\n",
    "plt.figure(figsize=(10, 8))\n",
    "plt.subplot(221)\n",
    "rasterplot(sim.trange(), sim.data[spikes])\n",
    "plt.ylabel(\"Neuron\")\n",
    "plt.xlim(0, 1)\n",
    "\n",
    "# Plot the soma voltages of the neurons\n",
    "plt.subplot(222)\n",
    "plt.plot(sim.trange(), sim.data[voltage][:, 0], 'r')\n",
    "plt.xlim(0, 1);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The top graph shows  the input signal in green\n",
    "and the filtered output spikes from the single neuron population in blue.\n",
    "The spikes (that are filtered) from the neuron\n",
    "are shown in the bottom graph on the left.\n",
    "On the right is the subthreshold voltages for the neuron."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
